<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import {callWithKeyDown, share_test} from './resources/share-test.js';
import {ShareError} from '/gen/third_party/blink/public/mojom/webshare/share_error.mojom.m.js';

async function assertRejectsWithError(promise, name) {
  try {
    await promise;
    assert_unreached('expected promise to reject with ' + name);
  } catch (error) {
    assert_equals(error.name, name);
  }
}

share_test(mock => {
  mock.pushShareResult('the title', 'the message', 'https://example.com/',
                       ShareError.CANCELED);
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          title: 'the title',
          text: 'the message',
          url: 'https://example.com/'
      }),
      'AbortError'));
}, 'share with user cancellation');

share_test(mock => {
  mock.pushShareResult('the title', 'the message', 'https://example.com/',
                       ShareError.INTERNAL_ERROR);
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          title: 'the title',
          text: 'the message',
          url: 'https://example.com/'
      }),
      'AbortError'));
}, 'share with internal error');

share_test(mock => {
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          title: 'the title',
          text: 'the message',
          url: 'data:foo'
      }),
      'TypeError'));
}, 'share with data url');

share_test(mock => {
  return callWithKeyDown(async () => {
    await assertRejectsWithError(
      navigator.share({
      }),
      'TypeError');

    return assertRejectsWithError(
      navigator.share({
      }),
      'NotAllowedError');
  });
}, 'share consumes user activation');

share_test(mock => {
  mock.pushShareResult('the title', 'the message', 'https://example.com/',
                       ShareError.CANCELED);
  return callWithKeyDown(async () => {
    const data = {
          title: 'the title',
          text: 'the message',
          url: 'https://example.com/'
    };
    const first = navigator.share(data);
    await assertRejectsWithError(
          navigator.share(data),
          'InvalidStateError');
    await assertRejectsWithError(
          navigator.share(data),
          'InvalidStateError');
    return assertRejectsWithError(
          first,
          'AbortError');
  } );
}, 'only one share at a time');


share_test(mock => {
  mock.pushShareResult('the title', 'the message', 'https://example.com/',
                       ShareError.CANCELED);
  return callWithKeyDown(async () => {
    const content = ['Hello'];
    const name = 'hello.txt';
    const options = {type: 'text/plain'};
    const excess_file_data = {
      files: Array(11).fill(new File(content, name, options))
    };
    await assertRejectsWithError(
          navigator.share(excess_file_data),
          'NotAllowedError');
    return callWithKeyDown(async () => {
      const data = {
            title: 'the title',
            text: 'the message',
            url: 'https://example.com/'
      };
      return assertRejectsWithError(
            navigator.share(data),
            'AbortError');
    });
  } );
}, 'Failed file share does not lead to InvalidStateError');

share_test(mock => {
  const kMaxTitleLength = 16 * 1024;
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          title: 'x'.repeat(kMaxTitleLength + 1)
      }),
      'NotAllowedError'));
}, 'share with excessive title');

share_test(mock => {
  const kMaxTextLength = 1 * 1024 * 1024;
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          text: 'y'.repeat(kMaxTextLength + 1)
      }),
      'NotAllowedError'));
}, 'share with excessive text');

share_test(mock => {
  const kMaxUrlLength = 16 * 1024;
  const prefix = 'https://example.com/?q=';
  return callWithKeyDown(() => assertRejectsWithError(
      navigator.share({
          url: prefix + 'z'.repeat(kMaxUrlLength + 1 - prefix.length)
      }),
      'NotAllowedError'));
}, 'share with excessive url');

</script>
